home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
WINDOWS
/
CLIPST.ARJ
/
CLIPSTAC.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-24
|
36KB
|
1,157 lines
// clipstac.cpp RHS 12/15/92
#include<stdio.h>
#include<string.h>
#include<memory.h>
#include"windlg.h"
#include"file.h"
#include"cursor.h"
#include"clipbrd.h"
#pragma hdrstop
#include"arraymgr.h"
#include"clipstac.h"
#include"csapi.h"
#include"dynarray.h"
#define MAXPATHLEN 144 // Date=8+1 time=6+1 format=8+1 size=6+1
#define DATETIMELEN 36 // 12/13/53 05:15a METAFILE 123456
#define OWNEROFFSET 32
#define CONTENTOFFSET 42
#define MAXNAMEBUF (MAXPATHLEN+DATETIMELEN)
#define LastChar(s) (s[strlen(s)-1])
#define MAXCLIPITEMS 500
template<class TYPE>
void DynArray<TYPE>::Delete(TYPE t)
{
for(int i = 0; i < num; i++)
if(t == TArray[i])
{
memmove(&TArray[i],&TArray[i+1],sizeof(TYPE)*(size-(i+1)));
num--;
return;
}
}
BOOL ArrayMgr::IsFirstDupe(int index)
{
DWORD offset = array[index].offset;
for(int i = 0; i < index; i++)
if(array[i].offset == offset)
return FALSE;
return TRUE;
}
BOOL ArrayMgr::IsDupe(int index)
{
return ((array[index].usage > 0) ? TRUE : FALSE);
}
void ArrayMgr::UpdateDupes(int index, DWORD newoffset)
{
DWORD oldoffset = array[index].offset;
for(int i = index; i < NumElements(); i++)
if(array[i].offset == oldoffset)
array[i].offset = newoffset;
}
void ArrayMgr::UpdateOffsets(DWORD offset)
{
for(int i = 0; i < NumElements(); i++)
array[i].offset += offset;
}
void ArrayMgr::DecrementUsage(DWORD offset)
{
for(int i = 0; i < NumElements(); i++)
if((array[i].offset == offset) && (array[i].usage))
array[i].usage--;
}
void ArrayMgr::SetUsage(DWORD offset, WORD usage)
{
for(int i = 0; i < NumElements(); i++)
if(array[i].offset == offset)
array[i].usage = usage;
}
typedef struct _clipobject
{
DWORD offset;
WORD format;
DWORD size;
char name[MAXNAMEBUF];
} CLIPOBJECT;
typedef struct _header
{
int NumElements;
int MaxElements;
int Size;
DWORD LastOffset;
} HEADER;
File StackFile;
Cursor myCursor;
char *szAppName = APPNAME;
char *szClipStacDat = "clipstac.dat";
char *szClipStacTemp = "clipstac.$$$";
char *szOwnerUnknown = "(Unknown) ";
#define MAXFMTS 10
char *fmts[MAXFMTS] =
{
"", // dummy so CF_TEXT (1) can be used to access "CF_TEXT", etc.
"TEXT ", // CF_TEXT
"BITMAP ", // CF_BITMAP
"METAFILE ", // CF_METAFILEPICT
"SYLK ", // CF_SYLK
"DIF ", // CF_DIF
"TIFF ", // CF_TIFF
"OEMTEXT ", // CF_OEMTEXT
"DIB ", // CF_DIB
"PALETTE ", // CF_PALETTE
};
char *fmtUnknown = "(Unknown)";
#define SC_USER (0xF000-1)
#define SC_ABOUT SC_USER
#define SC_AUTOPACK SC_USER-1
#define SC_AUTOLOAD SC_USER-2
char *szAbout = "About ClipStac...";
char *szAutoLoad = "AutoLoad";
char *szMaxItems = "MaxItems";
char *szAutoPack = "AutoPack";
BOOL bAutoLoad = FALSE;
BOOL bAutoPack = FALSE;
int lbItems = 0;
int MaxItems = MAXCLIPITEMS;
#define MAXWINDOWSPARM 256
char outbuf[MAXWINDOWSPARM];
BOOL FAR PASCAL _export DialogProc(HWND hDlg, unsigned message, WORD wParam, LONG lParam)
{
lParam = lParam; // turn off compiler warning
switch(message)
{
case WM_INITDIALOG:
SetDlgItemInt(hDlg,4,lbItems,FALSE);
return TRUE;
case WM_COMMAND:
if(wParam == IDOK || wParam == IDCANCEL)
{
EndDialog(hDlg, TRUE);
return TRUE;
}
break;
}
return FALSE;
}
class ClipStac : public WinDlg
{
// HWND hWndNextViewer;
char ownername[80];
HANDLE ListBoxHdl, TitleHdl;
ArrayMgr arrayMgr;
DynArray<HWND> dynArray;
HFONT hLBFont, hOldLBFont, hTFont, hOldTFont;
BOOL inPaste, fmtFound, newFile, inCopy;
char AppName[MAXPATHLEN];
HEADER header;
ClipBoard clp;
HWND ActiveWindow;
void UpdateListBox(CLIPOBJECT& clobj,WORD usage = 0);
public:
ClipStac(char *name);
void WMDRAWCLIPBOARD(WinAppMsg& m);
void WMTIMER(WinAppMsg& m);
void WMCOMMAND(WinAppMsg& m);
void WMSYSCOMMAND(WinAppMsg& m);
void WMCREATE(WinAppMsg& m);
void WMCHANGECBCHAIN(WinAppMsg& m);
void WMINITMENU(WinAppMsg& m);
void WMDESTROY(WinAppMsg& m);
void WMPAINT(WinAppMsg& m);
void WMUSER(WinAppMsg& m);
void WMCTLCOLOR(WinAppMsg& m);
void WMCLOSE(WinAppMsg& m);
void WMQUERYENDSESSION(WinAppMsg& m) { WMCLOSE(m); }
void WMACTIVATE(WinAppMsg& m);
void GetDateTime(CLIPOBJECT& clpobj);
int Find(LPSTR s);
void Init(void);
void ResizeFileHeader(void);
void PackFile(void);
DWORD NextSlot(void);
void SetNextSlot(CLIPOBJECT& clip);
void UpdateSystemMenu(void);
BOOL Copy(BOOL notify, int index = -1);
void AutoLoad(void);
BOOL Paste(BOOL notify);
void UpdateHeader(File& f);
LPSTR Get(int i);
DWORD FirstRecord(void) { return arrayMgr.Size()+sizeof(header); }
void InitListBox(void);
void DeleteItems(void);
void SetupClipObject(CLIPOBJECT& clip,int format,
DWORD size, char *ownername, LPSTR lpClipmem = NULL);
void CopyToTopOfStack(int& index);
BOOL SelectItem(BOOL notify, int& index);
BOOL Top(BOOL notify);
int NumItems(void) { return arrayMgr.NumElements(); }
};
void ClipStac::WMINITMENU(WinAppMsg&)
{
CheckMenuItem(GetSystemMenu(hWnd,0),
SC_AUTOLOAD,
(MF_BYCOMMAND | (bAutoLoad ? MF_CHECKED : MF_UNCHECKED)));
CheckMenuItem(GetSystemMenu(hWnd,0),
SC_AUTOPACK,
(MF_BYCOMMAND | (bAutoPack ? MF_CHECKED : MF_UNCHECKED)));
}
void ClipStac::WMDESTROY(WinAppMsg&)
{
clp.QuitViewers();
PostQuitMessage(0);
}
void ClipStac::UpdateSystemMenu(void)
{
HMENU hSysMenu = GetSystemMenu(hWnd,0);
RemoveMenu(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
RemoveMenu(hSysMenu, SC_SIZE, MF_BYCOMMAND);
AppendMenu(hSysMenu, MF_SEPARATOR, 0, NULL);
AppendMenu(hSysMenu, MF_STRING, SC_ABOUT, szAbout);
AppendMenu(hSysMenu, MF_STRING, SC_AUTOPACK, szAutoPack);
AppendMenu(hSysMenu, MF_STRING, SC_AUTOLOAD, szAutoLoad);
}
ClipStac::ClipStac(char *name) : WinDlg(name)
{
hLBFont = hOldLBFont = hTFont = hOldTFont = 0;
ListBoxHdl = TitleHdl = 0;
ActiveWindow = NULL;
// hWndNextViewer = NULL;
SetClassIcon("CLIPSTAC");
fmtFound = inPaste = newFile = inCopy = FALSE;
DelWinStyle(WS_VISIBLE);
bAutoLoad = GetProfileInt(szAppName,szAutoLoad,FALSE);
bAutoPack = GetProfileInt(szAppName,szAutoPack,FALSE);
MaxItems = GetProfileInt(szAppName,szMaxItems,MAXCLIPITEMS);
if((MaxItems > MAXCLIPITEMS) || (MaxItems < 1))
MaxItems = MAXCLIPITEMS; // in case user did something ridiculous
dynArray.Init(10);
// register ClipStac API messages!
WM_CLIPSTACREGISTER = RegisterWindowMessage(szWM_CLIPSTACREGISTER);
WM_CLIPSTACPUSH = RegisterWindowMessage(szWM_CLIPSTACPUSH);
WM_CLIPSTACPOP = RegisterWindowMessage(szWM_CLIPSTACPOP);
WM_CLIPSTACFIND = RegisterWindowMessage(szWM_CLIPSTACFIND);
WM_CLIPSTACGET = RegisterWindowMessage(szWM_CLIPSTACGET);
WM_CLIPSTACEXIT = RegisterWindowMessage(szWM_CLIPSTACEXIT);
WM_CLIPSTACDEREGISTER = RegisterWindowMessage(szWM_CLIPSTACDEREGISTER);
WM_CLIPSTACNUMITEMS = RegisterWindowMessage(szWM_CLIPSTACNUMITEMS);
}
DWORD ClipStac::NextSlot(void)
{
DWORD retval = arrayMgr.LastOffset();
if(retval == 0L)
return arrayMgr.Size()+sizeof(header);
return (retval+sizeof(CLIPOBJECT));
}
void ClipStac::SetNextSlot(CLIPOBJECT& clip)
{
DWORD newoffset =
(clip.offset+clip.size+sizeof(CLIPOBJECT)+
(clip.format == CF_BITMAP ? sizeof(BITMAP) : 0L));
if(arrayMgr.LastOffset() < newoffset)
arrayMgr.LastOffset(newoffset);
}
void ClipStac::WMCHANGECBCHAIN(WinAppMsg& m)
{ // viewer list has changed
if(m.wParam == clp.NextViewer) // our 'next' is removing itself
clp.NextViewer = LOWORD(m.lParam);
else if(clp.NextViewer) // not our 'next', tell our 'next'
SendMessage(clp.NextViewer,m.msg,m.wParam,m.lParam);
}
void ClipStac::AutoLoad(void)
{
char *p;
GetProfileString("windows","load","",outbuf,sizeof(outbuf));
strupr(outbuf);
bAutoLoad = !bAutoLoad;
// if Auto Load is selected and app name is not in LOAD= list
if(bAutoLoad && !strstr(outbuf,AppName))
{
strcpy(outbuf,AppName); // put WinColor in buffer
strcat(outbuf," "); // add blank and name to it
p = &LastChar(outbuf); // goto last character
p++; // set to the NULL
// append LOAD= list
GetProfileString("windows","load","",p,sizeof(outbuf)-(p-outbuf));
WriteProfileString("windows","load",outbuf);
}
// if Auto Load is not selected and app name is in LOAD= list
if(!bAutoLoad && (p = strstr(outbuf,AppName)))
{
*p = '\0'; // NULL at start of appname
p += strlen(AppName); // move past appname
strcat(outbuf,p); // copy everybody up
WriteProfileString("windows","load",outbuf);
}
}
BOOL ClipStac::Paste(BOOL notify)
{
inPaste = TRUE;
fmtFound = FALSE;
HWND hWndTemp = clp.NextViewer;
clp.NextViewer = 0;
SendMsg(WM_DRAWCLIPBOARD);
clp.NextViewer = hWndTemp;
inPaste = FALSE;
if(notify && !fmtFound)
MessageBox(hWnd,"No supported formats found or Clipboard is empty!",
szAppName,MB_OK);
return fmtFound;
}
void ClipStac::CopyToTopOfStack(int& index)
{
CLIPOBJECT clobj;
char name[MAXNAMEBUF];
SendMessage(ListBoxHdl,LB_GETTEXT,index,(LONG)(LPSTR)name);
char *p,*q;
p = &name[OWNEROFFSET];
//q = &name[CONTENTOFFSET];
SetupClipObject(clobj,arrayMgr[index]->format,arrayMgr[index]->size,p);
clobj.offset = arrayMgr[index]->offset;
UpdateListBox(clobj,arrayMgr[index]->usage+1);
index++;
}
BOOL ClipStac::SelectItem(BOOL notify, int& index)
{
index = SendMessage(ListBoxHdl,LB_GETCURSEL,0,0L);
if(index == LB_ERR || !arrayMgr.IsValid(index))
{
if(notify)
MessageBox(hWnd,"No item selected!",szAppName,MB_OK);
return FALSE;
}
return TRUE;
}
BOOL ClipStac::Top(BOOL notify)
{
int index;
if(!SelectItem(notify,index))
return FALSE;
CopyToTopOfStack(index);
return TRUE;
}
BOOL ClipStac::Copy(BOOL notify, int index)
{
BOOL retval = FALSE;
if(index == -1)
if(!SelectItem(notify,index))
return FALSE;
CopyToTopOfStack(index);
HANDLE hMemory;
if(arrayMgr[index]->format == CF_BITMAP)
{
BITMAP bitmap;
StackFile.ReadAt(arrayMgr[index]->offset+sizeof(CLIPOBJECT),
(WORD)sizeof(BITMAP),&bitmap);
HANDLE hBits = GlobalAlloc(GHND,arrayMgr[index]->size);
bitmap.bmBits = GlobalLock(hBits);
StackFile.ReadAt(arrayMgr[index]->offset+sizeof(CLIPOBJECT)+sizeof(BITMAP),
arrayMgr[index]->size,bitmap.bmBits);
hMemory = CreateBitmapIndirect(&bitmap);
GlobalUnlock(hBits);
GlobalFree(hBits);
}
else
{
hMemory = GlobalAlloc(GHND,arrayMgr[index]->size);
LPSTR lpClipmem = GlobalLock(hMemory);
StackFile.ReadAt(arrayMgr[index]->offset+sizeof(CLIPOBJECT),
arrayMgr[index]->size,(void far *)lpClipmem);
GlobalUnlock(hMemory);
}
if(!clp.Open())
{
if(notify)
MessageBox(hWnd,"Cannot open Clipboard!",szAppName,MB_OK);
}
else
{
inCopy = TRUE;
clp.Empty();
clp.SetData(arrayMgr[index]->format,hMemory);
clp.Close();
retval = TRUE;
}
return retval;
}
void ClipStac::WMPAINT(WinAppMsg&)
{
PAINTSTRUCT ps;
BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
}
char message[50];
void ClipStac::WMUSER(WinAppMsg& m)
{
if(m.msg == WM_CLIPSTACREGISTER) // returns our hWnd
{ // ClipStac's hWnd in LOWORD, put user's hWnd in HIWORD
LONG l = MAKELONG(hWnd,m.wParam);
PostMessage(m.wParam,WM_CLIPSTACREGISTER,0,l);
dynArray.Add(m.wParam);
m.userMsgUsed = TRUE;
}
if(m.msg == WM_CLIPSTACPUSH) // returns FALSE if unsuccessful
{
m.msgRetVal = Paste(FALSE);
m.userMsgUsed = TRUE;
}
if(m.msg == WM_CLIPSTACPOP) // returns FALSE if unsuccessful
{
m.msgRetVal = Copy(FALSE,m.wParam);
m.userMsgUsed = TRUE;
}
if(m.msg == WM_CLIPSTACFIND)
{
m.userMsgUsed = TRUE;
m.msgRetVal = Find((LPSTR)m.lParam);
}
if(m.msg == WM_CLIPSTACGET)
{
m.userMsgUsed = TRUE;
m.msgRetVal = (LONG)Get(m.wParam);
}
if(m.msg == WM_CLIPSTACDEREGISTER)
{
m.userMsgUsed = TRUE;
dynArray.Delete(m.wParam);
}
if(m.msg == WM_CLIPSTACNUMITEMS)
{
m.userMsgUsed = TRUE;
m.msgRetVal = NumItems();
}
}
void ClipStac::WMCTLCOLOR(WinAppMsg& m)
{
if(!ListBoxHdl && (HIWORD(m.lParam) == CTLCOLOR_LISTBOX))
{
ListBoxHdl = LOWORD(m.lParam);
SetTimer(hWnd,1,100,NULL);
}
if(!TitleHdl && (HIWORD(m.lParam) == CTLCOLOR_STATIC))
{
WORD iD = GetDlgCtrlID(LOWORD(m.lParam));
if(iD == IDM_TITLE)
{
TitleHdl = LOWORD(m.lParam);
SetTimer(hWnd,2,100,NULL);
}
}
DefWinProc(m);
}
void ClipStac::UpdateHeader(File& f)
{
header.NumElements = arrayMgr.NumElements();
header.MaxElements = arrayMgr.MaxElements();
header.Size = arrayMgr.Size();
header.LastOffset = arrayMgr.LastOffset();
f.WriteAt(0L,sizeof(header),&header);
f.WriteAt(0L+sizeof(header),
(WORD)arrayMgr.Size(),arrayMgr.Array());
}
void ClipStac::WMCLOSE(WinAppMsg&)
{
myCursor(WAIT);
if(StackFile.IsOpen())
{
UpdateHeader(StackFile);
StackFile.Close();
}
if(ListBoxHdl)
{
HDC hDC = GetDC(ListBoxHdl);
SelectObject(hDC,hOldLBFont);
ReleaseDC(ListBoxHdl,hDC);
SendMessage(ListBoxHdl,WM_SETFONT,hOldLBFont,FALSE);
DeleteObject(hLBFont);
}
if(TitleHdl)
{
HDC hDC = GetDC(TitleHdl);
SelectObject(hDC,hOldTFont);
ReleaseDC(TitleHdl,hDC);
SendMessage(TitleHdl,WM_SETFONT,hOldTFont,FALSE);
DeleteObject(hTFont);
}
WriteProfileString(szAppName,szAutoLoad,(bAutoLoad ? "1" : "0"));
WriteProfileString(szAppName,szAutoPack,(bAutoPack ? "1" : "0"));
#ifdef OLD
char buf[20];
sprintf(buf,"%d",MaxItems);
WriteProfileString(szAppName,szMaxItems,buf);
#endif
for(int i = 0; i < dynArray.NumItems(); i++)
PostMessage(dynArray[i],WM_CLIPSTACEXIT,hWnd,0L);
myCursor(ARROW);
DestroyWindow(hWnd);
}
LPSTR ClipStac::Get(int i)
{
CLIPOBJECT clobj;
if(arrayMgr.IsValid(i))
{
StackFile.ReadAt(arrayMgr[i]->offset,sizeof(clobj),&clobj);
return (LPSTR)clobj.name;
}
return (LPSTR)NULL;
}
int ClipStac::Find(LPSTR s)
{
int i;
CLIPOBJECT clobj;
for(i = 0; i < arrayMgr.NumElements(); i++)
{
StackFile.ReadAt(arrayMgr[i]->offset,sizeof(clobj),&clobj);
if(_fstrstr(clobj.name,s))
return i;
}
return -1;
}
void ClipStac::WMCREATE(WinAppMsg& m)
{
clp.SethWnd(hWnd);
char dir[MAXPATHLEN];
BOOL tried_already = FALSE;
UpdateSystemMenu();
GetModuleFileName(GetClassWord(hWnd,GCW_HMODULE),AppName, MAXPATHLEN-1);
GetWindowsDirectory(dir,sizeof(dir));
strcat(dir,"\\");
strcat(dir,szClipStacDat);
StackFile.SetName(dir);
tryopen:
if(!StackFile.Open(OF_READWRITE /* | OF_SHARE_EXCLUSIVE */))
{
if(!tried_already)
{
if(MessageBox(hWnd,"Unable to open CLIPSTAC.DAT...create it?",
szAppName,MB_YESNO | MB_ICONQUESTION) == IDYES)
{
if(StackFile.Create(0))
{
newFile = TRUE;
StackFile.Close();
tried_already = TRUE;
goto tryopen;
}
else
MessageBox(hWnd,"Unable to create CLIPSTAC.DAT...terminating.",
szAppName,MB_OK);
}
else
MessageBox(hWnd,"Unable to open CLIPSTAC.DAT...terminating",
szAppName, MB_OK);
}
SendMsg(WM_CLOSE);
m.msgRetVal = -1L;
return;
}
if(StackFile.Size() == 0L)
newFile = TRUE;
SetFocus(GetDlgItem(hWnd, IDM_COPY));
}
void ClipStac::GetDateTime(CLIPOBJECT& clpobj)
{
BYTE hour, minutes, pm, month, day, year;
_AH = 0x2A;
asm int 0x21;
month = _DH;
day = _DL;
year = _CX-1900;
_AH = 0x2C;
asm int 0x21;
hour = _CH;
minutes = _CL;
// seconds = _DH;
// hundreds = _DL;
pm = FALSE;
if(hour >= 12)
{
pm = TRUE;
if(hour > 12)
hour -= 12;
}
if(!hour)
hour = 12;
sprintf(clpobj.name,"%02d/%02d/%02d %02d:%02d%c ",
month,day,year,hour,minutes,(pm ? 'p' : 'a'));
}
void ClipStac::WMCOMMAND(WinAppMsg& m)
{
switch(m.wParam)
{
case IDM_LISTBOX:
if(HIWORD(m.lParam) == LBN_DBLCLK)
SendMsg(WM_COMMAND,IDM_COPY);
break;
case IDM_COPY:
Copy(TRUE);
break;
case IDM_PASTE:
Paste(TRUE);
break;
case IDM_TOP:
Top(TRUE);
break;
case IDM_DELETE:
{
int index;
if(SelectItem(TRUE,index))
{
SendMessage(ListBoxHdl,LB_DELETESTRING,index,0L);
arrayMgr.Delete(index);
int count = SendMessage(ListBoxHdl,LB_GETCOUNT,0,0L);
if((count > 0) && (count != index))
SendMessage(ListBoxHdl,LB_SETCURSEL,index,0L);
}
}
break;
case IDM_HELP:
{
#if defined(__BORLANDC__)
DialogBox(GetInstance(), "HELP", hWnd, (FARPROC)DialogProc);
#else
FARPROC lpDlgProc = MakeProcInstance((FARPROC)DialogProc,GetInstance());
DialogBox(GetInstance(), "HELP", hWnd, lpDlgProc);
FreeProcInstance(lpDlgProc);
#endif
SetFocus(GetDlgItem(hWnd,IDM_HELP));
}
break;
case IDM_PACK:
if(MessageBox(hWnd,"Packing CLIPSTAC.DAT may take some time...proceed?",szAppName,
MB_APPLMODAL | MB_ICONEXCLAMATION | MB_OKCANCEL) == IDOK)
{
myCursor(WAIT);
int index;
SelectItem(FALSE,index);
PackFile();
DeleteItems();
InitListBox();
if(index > 0)
SendMessage(ListBoxHdl,LB_SETCURSEL,index,0L);
myCursor(ARROW);
}
break;
}
}
void ClipStac::UpdateListBox(CLIPOBJECT& clobj,WORD usage)
{
int index, cursel;
cursel = SendDlgItemMessage(hWnd,IDM_LISTBOX,LB_GETCURSEL,0,0L);
if((index = SendDlgItemMessage(hWnd,IDM_LISTBOX,LB_INSERTSTRING,
0,(LONG)(LPSTR)clobj.name)) < 0)
MessageBox(hWnd,"Unable to insert data into List Box!",szAppName,MB_OK);
else
{
while(SendDlgItemMessage(hWnd,IDM_LISTBOX,LB_GETCOUNT,0,0L) > MaxItems)
SendDlgItemMessage(hWnd,IDM_LISTBOX,LB_DELETESTRING,MaxItems,0L);
arrayMgr.Insert(clobj.offset,clobj.format,clobj.size,usage);
UpdateHeader(StackFile);
if(IsIconic(hWnd))
InvalidateRect(hWnd,NULL,TRUE);
}
if(index > 0)
MessageBox(hWnd,"Insert index not 0!",szAppName,MB_OK);
if(cursel != LB_ERR)
SendDlgItemMessage(hWnd,IDM_LISTBOX,LB_SETCURSEL,cursel+1,0L);
}
void ClipStac::SetupClipObject(CLIPOBJECT& clobj,int format,
DWORD size, char *ownername,LPSTR text)
{
memset(&clobj,0,sizeof(clobj));
clobj.format = format;
clobj.size = size;
GetDateTime(clobj);
if(format >= MAXFMTS)
strcat(clobj.name,fmtUnknown);
else
strcat(clobj.name,fmts[format]);
char buf[20];
sprintf(buf,"%6lu ",clobj.size);
strcat(clobj.name,buf);
if(!text)
strcat(clobj.name,ownername);
else
{
char *p = strrchr(ownername,'\\');
if(p && p < ownername+OWNEROFFSET)
{
p++;
char *q = strchr(p,'.');
if(q)
{
while(q < p+10)
*q++ = ' ';
*q = '\0';
}
}
else
p = ownername;
strcat(clobj.name,p);
if(format == CF_TEXT || format == CF_OEMTEXT)
{
strcat(clobj.name,"\"");
_fstrncpy(&clobj.name[7+DATETIMELEN],text,MAXPATHLEN-11);
}
else
memset(&clobj.name[6+DATETIMELEN],'.',MAXPATHLEN-11);
}
}
void ClipStac::WMACTIVATE(WinAppMsg& m)
{
if(!m.wParam) // window is inactive, save focus
ActiveWindow = GetFocus();
else // window is being activated, set focus
{
if(ActiveWindow)
SetFocus(ActiveWindow);
else
SetFocus(GetDlgItem(hWnd, IDM_COPY));
}
}
void ClipStac::WMDRAWCLIPBOARD(WinAppMsg& m)
{
if(clp.NextViewer) // notify next viewer
SendMessage(clp.NextViewer, m.msg, m.wParam, m.lParam);
if(inCopy)
{
inCopy = FALSE;
DefWinProc(m);
return;
}
// clipboard contents have changed
if(!inPaste && !clp.GetOwner())
{
DefWinProc(m);
return;
}
if(!inPaste)
{
WORD hModule = GetClassWord(clp.GetOwner(),GCW_HMODULE);
GetModuleFileName(hModule,ownername,sizeof(ownername)-1);
}
else
strcpy(ownername,szOwnerUnknown);
int format;
if(!clp.Open())
MessageBox(hWnd,"Cannot open Clipboard!",szAppName,MB_OK);
else
{
myCursor(WAIT);
HANDLE hBitmap;
BITMAP bitmap;
DWORD bmpSize;
for(format = 0; format = clp.EnumFormats(format) ; )
{
switch(format)
{
case CF_BITMAP:
{
hBitmap = clp.GetData(format);
if(hBitmap)
{
bitmap;
GetObject(hBitmap,sizeof(BITMAP),(LPSTR)&bitmap);
bmpSize = (DWORD)bitmap.bmWidthBytes * bitmap.bmHeight * bitmap.bmPlanes;
}
}
// fall thru
case CF_TEXT:
case CF_SYLK:
case CF_DIF:
case CF_OEMTEXT:
case CF_DIB:
{
fmtFound = TRUE;
HANDLE hClipMemory = (format == CF_BITMAP ) ? hBitmap :
clp.GetData(format);
if(hClipMemory)
{
CLIPOBJECT clobj;
{
if(format == CF_TEXT || format == CF_OEMTEXT)
{
LPSTR lpClipmem = GlobalLock(hClipMemory);
SetupClipObject(clobj,format,
(format == CF_BITMAP) ? bmpSize : GlobalSize(hClipMemory),
ownername, lpClipmem);
GlobalUnlock(hClipMemory);
}
else
SetupClipObject(clobj,format,
(format == CF_BITMAP) ? bmpSize : GlobalSize(hClipMemory),
ownername, (LPSTR)ownername);
}
StackFile.Offset(NextSlot());
clobj.offset = StackFile.CurPosition();
StackFile.WriteAt(clobj.offset,(WORD)sizeof(CLIPOBJECT),&clobj);
if(format == CF_BITMAP)
{
StackFile.WriteAt(clobj.offset+sizeof(CLIPOBJECT),
(WORD)sizeof(BITMAP),&bitmap);
HANDLE hBits = GlobalAlloc(GHND, bmpSize);
LPSTR lpClipmem = GlobalLock(hBits);
GetBitmapBits(hBitmap,bmpSize,lpClipmem);
StackFile.WriteAt(clobj.offset+sizeof(CLIPOBJECT)+sizeof(BITMAP),
bmpSize,lpClipmem);
GlobalUnlock(hBits);
GlobalFree(hBits);
}
else
{
LPSTR lpClipmem = GlobalLock(hClipMemory);
StackFile.WriteAt(clobj.offset+sizeof(CLIPOBJECT),
clobj.size,(void far *)lpClipmem);
GlobalUnlock(hClipMemory);
}
UpdateListBox(clobj);
SetNextSlot(clobj);
UpdateHeader(StackFile);
}
}
break;
default:
break;
}
}
clp.Close();
myCursor(ARROW);
}
}
void ClipStac::WMTIMER(WinAppMsg& m)
{
KillTimer(hWnd,m.wParam);
switch(m.wParam)
{
case 2:
{
HDC hDC = GetDC(TitleHdl);
hTFont = GetStockObject(SYSTEM_FIXED_FONT);
hOldTFont = SelectObject(hDC,hTFont);
ReleaseDC(TitleHdl,hDC);
SendMessage(TitleHdl,WM_SETFONT,hTFont,TRUE);
}
break;
case 1:
{
HDC hDC = GetDC(ListBoxHdl);
hLBFont = GetStockObject(SYSTEM_FIXED_FONT);
hOldLBFont = SelectObject(hDC,hLBFont);
ReleaseDC(ListBoxHdl,hDC);
SendMessage(ListBoxHdl,WM_SETFONT,hLBFont,FALSE);
Init();
}
break;
}
}
void ClipStac::ResizeFileHeader(void)
{
WORD oldMax = arrayMgr.MaxElements(); // get original array size
DWORD firstOffset = FirstRecord(); // get *before* resizing the array
if(!arrayMgr.ReSize(MaxItems)) // if re-alloc fails, go with what
MaxItems = arrayMgr.MaxElements(); // we have
if(oldMax < MaxItems) // if array was expanded
{
char dir[MAXPATHLEN];
GetWindowsDirectory(dir,sizeof(dir));
strcat(dir,"\\");
strcat(dir,szClipStacTemp); // create C:\WINDOWS\CLIPSTAC.$$$ name
File TempFile(dir); // create temp File object
TempFile.Create(0); // create the file
arrayMgr.UpdateOffsets(FirstRecord()-firstOffset); // after re-sizing
UpdateHeader(TempFile); // write the new header to the file
TempFile.Append(StackFile,firstOffset); // tack on remainder of org file
TempFile.Close(); // close 'em
StackFile.Close();
StackFile.Delete(); // delete the old guy
TempFile.Rename(StackFile.GetName()); // rename the disk file
StackFile.Open(OF_READWRITE); // re-open it
}
else // if array shrunk
UpdateHeader(StackFile);
}
void ClipStac::PackFile(void)
{
#ifdef OLD
DWORD curroffset = FirstRecord();
WORD compress = FALSE;
for(int i = arrayMgr.NumElements()-1 ; i >= 0; i--) // for each item in array
{ // calculate it's true size
if(arrayMgr.IsDupe(i,arrayMgr[i]->offset)) // if already copied,
continue; // don't copy it
DWORD size = arrayMgr[i]->size + sizeof(CLIPOBJECT);
if(arrayMgr[i]->format == CF_BITMAP)
size += sizeof(BITMAP);
if(arrayMgr[i]->offset != curroffset) // if not at the right offset
{ // copy it to new location
StackFile.CopyBytes(curroffset,arrayMgr[i]->offset,size);
arrayMgr[i]->offset = curroffset; // reset offset in header
compress = TRUE;
}
curroffset += size; // set for next location in file
}
if(!compress)
return;
UpdateHeader(StackFile); // write the header
char dir[MAXPATHLEN];
GetWindowsDirectory(dir,sizeof(dir));
strcat(dir,"\\");
strcat(dir,szClipStacTemp); // create C:\WINDOWS\CLIPSTAC.$$$ name
File TempFile(dir); // create temp file object
TempFile.Create(0);
TempFile.Append(StackFile,0,curroffset);
TempFile.Close(); // close 'em
StackFile.Close();
StackFile.Delete(); // delete the old guy
TempFile.Rename(StackFile.GetName()); // rename the disk file
StackFile.Open(OF_READWRITE); // re-open it
#else
char dir[MAXPATHLEN];
GetWindowsDirectory(dir,sizeof(dir));
strcat(dir,"\\");
strcat(dir,szClipStacTemp); // create C:\WINDOWS\CLIPSTAC.$$$ name
File TempFile(dir); // create temp file object
TempFile.Create(0);
DWORD tempOffset = FirstRecord();
HANDLE hMem = GlobalAlloc(GHND,0xffff);
LPSTR buffer = GlobalLock(hMem);
TempFile.Append(StackFile,0,tempOffset,buffer);
for(int i = 0; i < arrayMgr.NumElements() ; i++) // for each item in array
{
if(arrayMgr.IsDupe(i)) // if dupe
if(!arrayMgr.IsFirstDupe(i)) // but a subsequent one,
continue;
// calculate it's true size
DWORD size = arrayMgr[i]->size + sizeof(CLIPOBJECT);
if(arrayMgr[i]->format == CF_BITMAP)
size += sizeof(BITMAP); // if bitmap, add size of BITMAP
TempFile.Append(StackFile,arrayMgr[i]->offset,size+arrayMgr[i]->offset,buffer);
if(arrayMgr.IsDupe(i)) // if it's a dupe
arrayMgr.UpdateDupes(i,tempOffset); // update all of them
else
arrayMgr[i]->offset = tempOffset;
tempOffset += size; // set for next location in Tempfile
}
GlobalUnlock(hMem);
GlobalFree(hMem);
arrayMgr.LastOffset(tempOffset);
UpdateHeader(TempFile);
TempFile.Close(); // close 'em
StackFile.Close();
StackFile.Delete(); // delete the old guy
TempFile.Rename(StackFile.GetName()); // rename the disk file
StackFile.Open(OF_READWRITE); // re-open it
#endif
}
void ClipStac::Init(void)
{
myCursor(WAIT);
// initialize list box here...
if(newFile)
{
arrayMgr.Init(MaxItems);
UpdateHeader(StackFile);
newFile = FALSE;
}
else // read array table from existing file
{
// go to array table offset
StackFile.ReadAt(0L,sizeof(header),&header);
arrayMgr.Init(header.MaxElements); // create array buffer and init maxEl
arrayMgr.SetNumElements(header.NumElements); // init numEl
arrayMgr.LastOffset(header.LastOffset); // init lastoffset
// read the array table into array
StackFile.ReadAt(0L+sizeof(header),
(WORD)arrayMgr.Size(),arrayMgr.Array());
if(arrayMgr.MaxElements() != MaxItems) // if array needs resizing
ResizeFileHeader(); // do it.
if(bAutoPack) // if compression turned on
PackFile(); // do it.
InitListBox();
}
clp.JoinViewers(); // become part of Clipboard chain
myCursor(ARROW);
}
void ClipStac::DeleteItems(void)
{
while(SendDlgItemMessage(hWnd,IDM_LISTBOX,LB_DELETESTRING,0,0L) > 0)
;
}
void ClipStac::InitListBox(void)
{
int i;
CLIPOBJECT clobj;
for(i = arrayMgr.NumElements()-1; i >= 0; i--)
{
StackFile.ReadAt(arrayMgr[i]->offset,
sizeof(CLIPOBJECT),&clobj);
if((SendDlgItemMessage(hWnd,IDM_LISTBOX,LB_INSERTSTRING,
0,(LONG)(LPSTR)clobj.name)) < 0)
{
MessageBox(hWnd,"Unable to insert data into List Box!",szAppName,MB_OK);
break;
}
}
}
void ClipStac::WMSYSCOMMAND(WinAppMsg& m)
{
switch(m.wParam)
{
case SC_ABOUT:
{
lbItems = SendMessage(ListBoxHdl,LB_GETCOUNT,0,0L);
#if defined(__BORLANDC__)
DialogBox(GetInstance(), "ABOUTBOX", hWnd, (FARPROC)DialogProc);
#else
FARPROC lpDlgProc = MakeProcInstance((FARPROC)DialogProc,GetInstance());
DialogBox(GetInstance(), "ABOUTBOX", hWnd, lpDlgProc);
FreeProcInstance(lpDlgProc);
#endif
break;
}
case SC_AUTOLOAD:
AutoLoad();
break;
case SC_AUTOPACK:
bAutoPack = !bAutoPack;
break;
default:
DefWinProc(m);
break;
}
}
int PASCAL WinMain(HANDLE, HANDLE, LPSTR, int)
{
myCursor(WAIT);
ClipStac MyWin(szAppName);
if(MyWin.GetPrevInstance())
{
myCursor(ARROW);
MessageBox(NULL,"ClipStac already running!",szAppName,MB_OK);
return 0;
}
MyWin.Display(); // open the window
myCursor(ARROW);
return MyWin.Run(); // process any messages
}